﻿using System;
using System.Collections.Generic;

namespace ZXW.DotNet.Common.Basic.ObjectManagement.Managers
{
    /// <summary>
    /// ISamePriorityObjectManager 同一优先级对象管理器，
    /// 用于管理同一优先级的所有对象，
    /// 这些对象将按照先来后到的顺序确定其优先顺序（“第二优先级”）。
    /// 该接口的实现必须保证是线程安全的。
    /// </summary>
    /// <typeparam name="T">要被管理的对象的类型</typeparam>
    public interface ISamePriorityObjectManager<T>
    {   
        /// <summary>
        /// AddWaiter 添加一个等待者。如果等待者在管理器中已经存在，则直接返回。
        /// </summary>       
        void AddWaiter(T waiter);

        /// <summary>
        /// Count 当前管理器中等待者的数量。
        /// </summary>
        int Count { get; }

        /// <summary>
        /// GetNextWaiter 返回等待时间最长的waiter。
        /// 注意，返回时并不会从等待列表中删除waiter。
        /// 如果要删除某个等待者，请调用RemoveWaiter。
        /// </summary>       
        T GetNextWaiter();

        /// <summary>
        /// GetWaitersByPriority 按照等待者加入的先后顺序返回等待者数组,
        /// 数组中index越小的等待者其等待时间越长，其优先级也越高。
        /// </summary>       
        T[] GetWaitersByPriority();

        /// <summary>
        /// RemoveWaiter 从管理器中移除指定的等待者。
        /// </summary>        
        void RemoveWaiter(T waiter);

        /// <summary>
        /// Clear 清空管理器中的所有等待者。
        /// </summary>
        void Clear();

        /// <summary>
        /// Contains 管理器中是否存在指定的等待者。
        /// </summary>       
        bool Contains(T waiter);
    }
}
/*

在ISamePriorityObjectManager所表述的语义环境中，
被管理的对象称为“等待者”waiter――这表示一个对象等待被处理。
 * 
关于SamePriorityObjectManager的实现，有以下几点需要说明：
（1）其内部是使用LinkedList(双向链表)而不是Queue来存储等待者的，其主要原因在于SamePriorityObjectManager需要支持移除管理器中任一等待者的RemoveWaiter方法。
 * 由于Queue本身不支持任意位置的删除功能，所以我使用了LinkedList。新加入的等待者将被放在LinkedList的最后位置。
 * 
（2）当管理器中没有任何等待者时，GetNextWaiter方法将返回default(T)，如果T是值类型，则此时GetNextWaiter返回的可能并不是一个你所期望的对象。所以，如果T是值类型，在调用GetNextWaiter之前先访问一下其Count属性确保管理器中还有等待者存在。
 * 
（3）SamePriorityObjectManager使用了前面介绍的SmartRWLocker来对内部的waiterList进行读写锁控制。
 
 */